using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

using needle.UI.Controls.Flat.Windows.Docking;
using needle.UI.Controls.Flat.Windows.Forms;
using needle.UI.Controls.Flat.Windows.Forms.Collections;
using needle.UI.Controls.Flat.Windows.Forms.Helpers;

namespace needle.UI.Controls.Flat.Windows.Docking
{
    [ToolboxItem(false)]
    public class ZoneSequence : Zone, IHotZoneSource, IZoneMaximizeWindow, global::needle.UI.Controls.Flat.Windows.Forms.IResizeSource
    {
        protected struct Position
        {
            private int length;
			
			public int Length
			{
				get{return this.length;}
				set{this.length = value;}
			}
        }

        protected const int mspacePrecision = 3;
        protected const int mhotVectorBeforeControl = 5;

        protected Direction mdirection;
        protected needle.UI.Controls.Flat.Windows.Forms.ResizeBar mresizeBar;
        protected Window mmaximizedWindow;
		protected bool msuppressReposition;
		protected bool mzoneMinMax;
	
        public event EventHandler RefreshMaximize;

		#region Constructors
		
		public ZoneSequence(DockingManager manager)
            : base(manager)
        {
            InternalConstruct(Direction.Vertical, true);
        }

        public ZoneSequence(DockingManager manager, State state, Direction direction, bool zoneMinMax)
            : base(manager, state)
        {
            InternalConstruct(direction, zoneMinMax);
        }

        protected void InternalConstruct(Direction direction, bool zoneMinMax)
        {
            mdirection = direction;
            mmaximizedWindow = null;
			msuppressReposition = false;
			mzoneMinMax = zoneMinMax;

            mresizeBar = new needle.UI.Controls.Flat.Windows.Forms.ResizeBar(mdirection, this);

            Controls.Add(mresizeBar);

            this.Size = new Size(0,0);		

			this.BackColor = SystemColors.Control;
			this.ForeColor = SystemColors.ControlText;
        }

		#endregion

		#region Virtuals

		public virtual void OnRefreshMaximize(EventArgs e)
		{
			if (RefreshMaximize != null)
				RefreshMaximize(this, e);
		}

		protected void GetZoneContentFriends(Content c,
			out StringCollection zoneBest,
			out StringCollection zoneNext,
			out StringCollection zonePrevious,
			out StringCollection zoneNextAll,
			out StringCollection zonePreviousAll)
		{

			zoneBest = ZoneHelper.ContentNamesInPriority(this,c);

			zoneNext = new StringCollection();
			zonePrevious = new StringCollection();
			zoneNextAll = new StringCollection();
			zonePreviousAll = new StringCollection();

			bool before = true;

			foreach(Control control in mmanager.Container.Controls)
			{
				Zone z = control as Zone;

				if (z != null)
				{
					if (z == this)
						before = false;
					else
					{
						ContentCollection newContent = ZoneHelper.Contents(z);

						foreach(Content content in newContent)
						{
							if (before)
							{
								if (z.State == this.State)
									zonePrevious.Add(content.Title);

								zonePreviousAll.Add(content.Title);
							}
							else
							{
								if (z.State == this.State)
									zoneNext.Add(content.Title);

								zoneNextAll.Add(content.Title);
							}
						}

						newContent.Clear();
					}
				}
			}
		}

		protected void GetWindowContentFriends(Window match, 
			out StringCollection best,
			out StringCollection nex,
			out StringCollection previous)
		{
			best = new StringCollection();
			nex = new StringCollection();
			previous = new StringCollection();

			bool before = true;

			foreach(Window w in mwindows)
			{
				WindowContent wc = w as WindowContent;

				if (w == match)
				{
					if (wc != null)
					{
						foreach(Content content in wc.Contents)
							best.Add(content.Title);
					}

					before = false;
				}
				else
				{
					if (wc != null)
					{
						foreach(Content content in wc.Contents)
						{
							if (before)
								previous.Add(content.Title);
							else
								nex.Add(content.Title);
						}
					}
				}
			}

		}

		protected void AddHotZoneWithIndex(HotZoneCollection collection, Rectangle zoneArea, int length, int index)
		{
			Rectangle hotArea = zoneArea;
			Rectangle newSize = zoneArea;

			if (mdirection == Direction.Vertical)
			{
				hotArea.Height = mhotVectorBeforeControl;
				newSize.Height = length;
			}
			else
			{
				hotArea.Width = mhotVectorBeforeControl;
				newSize.Width = length;
			}

			collection.Add(new HotZoneSequence(hotArea, newSize, this, index));				
		}
		
		protected void ModifyWindowSpace(Window w, int vector)
		{
			if (mmaximizedWindow != null)
			{
				foreach(Window entry in mwindows)
				{
					if (entry == mmaximizedWindow)
						entry.ZoneArea = 100m;
					else
						entry.ZoneArea = 0m; 
				}

				mmaximizedWindow = null;

				OnRefreshMaximize(EventArgs.Empty);
			}

			Rectangle clientRect = this.ClientRectangle;

			RepositionZoneBar(ref clientRect);

			int space;

			int newLength = vector;
			
			if (mdirection == Direction.Vertical)
			{
				space = clientRect.Height;

				newLength += w.Height;
				newLength -= w.MinimalSize.Height;
			}
			else
			{
				space = clientRect.Width;

				newLength += w.Width;
				newLength -= w.MinimalSize.Width;
			}

			int barSpace = 0;

			Position[] positions = new Position[Controls.Count - 1];

			AllocateMandatorySizes(ref positions, ref barSpace, ref space);

			Decimal newPercent = 0m;

			if ((newLength > 0) && (space > 0))
				newPercent = (Decimal)newLength / (Decimal)space * 100;

			Decimal reallocate = newPercent - w.ZoneArea;

			Window nexWindow = mwindows[mwindows.IndexOf(w) + 1];

			if ((nexWindow.ZoneArea - reallocate) < 0m)
				reallocate = nexWindow.ZoneArea;
	
			w.ZoneArea += reallocate;

			nexWindow.ZoneArea -= reallocate;
			
			RepositionControls();
		}

		protected Decimal ReduceAreaEvenly(int thisIndex, Decimal windowAllocation)
		{
			Decimal removed = 0m;

			for(int index=thisIndex + 1; index<mwindows.Count; index++)
			{
				Decimal zoneArea = mwindows[index].ZoneArea;

				if (zoneArea > 0m)
				{
					if (zoneArea >= windowAllocation)
					{
						mwindows[index].ZoneArea -= windowAllocation;

						removed += windowAllocation;
					}
					else
					{
						mwindows[index].ZoneArea = 0m;

						removed += zoneArea;
					}
				}
			}

			return removed;
		}
		
		protected void RemoveWindowSpace(Window w)
		{
			if (mwindows.Count == 1)
			{
				mwindows[0].ZoneArea = 100m;
			}
			else
			{
				if (w.ZoneArea > 0)
				{
					Decimal totalAllocated = 0m;

					Decimal freedSpace = w.ZoneArea / (mwindows.Count - 1);

					foreach(Window entry in mwindows)
					{
						if (entry != w)
						{
							Decimal newSpace = Decimal.Round(entry.ZoneArea + freedSpace, mspacePrecision);                            

							entry.ZoneArea = newSpace;
                            
							totalAllocated += newSpace;
						}
					}

					if (totalAllocated > 100m)
					{
						Decimal correction = totalAllocated - 100m;

						foreach(Window entry in mwindows)
						{
							if (entry != w)
							{
								entry.ZoneArea = totalAllocated - 100m;
								break;
							}
						}
					}
					else if (totalAllocated < 100m)
					{
						Decimal correction = 100m - totalAllocated;

						foreach(Window entry in mwindows)
						{
							if (entry != w)
							{
								entry.ZoneArea += 100m - totalAllocated;
								break;
							}
						}
					}

					w.ZoneArea = 0m;
				}
			}
		}

		protected void RepositionControls()
		{
			if (msuppressReposition)
			{
				msuppressReposition = false;
				return;
			}

			Rectangle clientRect = this.ClientRectangle;

			RepositionZoneBar(ref clientRect);

			if (mwindows.Count > 0)
			{
				int space;
				
				int delta;

				if (mdirection == Direction.Vertical)
				{
					space = clientRect.Height;
					delta = clientRect.Top;
				}
				else
				{
					space = clientRect.Width;
					delta = clientRect.Left;
				}

				if (space < 0)
					space = 0;

				int barSpace = 0;
				int allocation = space;

				Position[] positions = new Position[Controls.Count - 1];

				AllocateMandatorySizes(ref positions, ref barSpace, ref space);
				if (space > 0)
				{
					AllocateRemainingSpace(ref positions, space);
				}
				RepositionControls(ref positions, clientRect, delta);
			}
		}

		protected void AllocateMandatorySizes(ref Position[] positions, ref int barSpace, ref int space)
		{
			for(int index=0; index<(Controls.Count - 1); index++)
			{
				ResizeBar bar = Controls[index] as ResizeBar;

				if (bar != null)
				{
					positions[index].Length = bar.Length;

					barSpace += positions[index].Length;
				}
				else
				{
					Window w = Controls[index] as Window;

					if (w != null)
					{
						Size minimal = w.MinimalSize;
						if (mdirection == Direction.Vertical)
							positions[index].Length = minimal.Height;
						else
							positions[index].Length = minimal.Width;
					}
				}

				space -= positions[index].Length;
			}			
		}

		protected void AllocateRemainingSpace(ref Position[] positions, int windowSpace)
		{
			int allocated = 0;

			for(int index=0; index<(Controls.Count - 1); index++)
			{
				Window w = Controls[index] as Window;

				if ((w != null) && ((mmaximizedWindow == null) || ((mmaximizedWindow != null) && (mmaximizedWindow == w))))
				{
					int extra;
					
					if (mmaximizedWindow == null)				
					{
						extra = (int)(windowSpace / 100m * w.ZoneArea);

						if (index == (Controls.Count - 1))
						{
							extra = windowSpace - allocated;
						}
					}
					else
					{
						extra = windowSpace - allocated;
					}

					positions[index].Length += extra;

					allocated += extra;
				}
			}
		}

		protected void RepositionControls(ref Position[] positions, Rectangle clientRect, int delta)
		{
			for(int index=0; index<(Controls.Count - 1); index++)
			{
				int newDelta = positions[index].Length;

				ResizeBar bar = Controls[index] as ResizeBar;

				if (bar != null)
				{
					if (mdirection == Direction.Vertical)
					{
						bar.Location = new Point(clientRect.X, delta);
						bar.Width = clientRect.Width;
						bar.Height = newDelta;
						delta += newDelta;
					}
					else
					{
						bar.Location = new Point(delta, clientRect.Y);
						bar.Height = clientRect.Height;
						bar.Width = newDelta;
						delta += newDelta;
					}
				}
				else
				{
					Window w = Controls[index] as Window;

					if (w != null)
					{
						if (newDelta == 0)
							w.Hide();
						else
						{
							if (mdirection == Direction.Vertical)
							{
								w.Location = new Point(clientRect.X, delta);
								w.Width = clientRect.Width;
								w.Height = newDelta;
							}
							else
							{
								w.Location = new Point(delta, clientRect.Y);
								w.Height = clientRect.Height;
								w.Width = newDelta;
							}

							if (!w.Visible)
								w.Show();
							delta += newDelta;
						}
					}
				}
			}			
		}

		protected void RepositionZoneBar(ref Rectangle clientRect)
		{
			Rectangle barRect;

			int length = mresizeBar.Length;
			
			bool resizeBarPresent = ((this.Dock != DockStyle.Fill) && (this.Dock != DockStyle.None));

			switch(mstate)
			{
				case State.DockLeft:
					mresizeBar.Direction = Direction.Horizontal;
					barRect = new Rectangle(this.Width - length, 0, length, this.Height);
					
					if (resizeBarPresent)
						clientRect.Width -= length;
					break;
				case State.DockTop:
					mresizeBar.Direction = Direction.Vertical;
					barRect = new Rectangle(0, this.Height - length, this.Width, length);

					if (resizeBarPresent)
						clientRect.Height -= length;
					break;
				case State.DockRight:
					mresizeBar.Direction = Direction.Horizontal;
					barRect = new Rectangle(0, 0, length, this.Height);

					if (resizeBarPresent)
					{
						clientRect.X += length;
						clientRect.Width -= length;
					}
					break;
				case State.DockBottom:
					mresizeBar.Direction = Direction.Vertical;
					barRect = new Rectangle(0, 0, this.Width, length);

					if (resizeBarPresent)
					{
						clientRect.Y += length;
						clientRect.Height -= length;
					}
					break;
				case State.Floating:
				default:
					mresizeBar.Direction = Direction.Horizontal;
					barRect = new Rectangle(0, 0, 0, 0);
					break;
			}

			if (resizeBarPresent)
			{
				mresizeBar.Location = new Point(barRect.X, barRect.Y);
				mresizeBar.Size = new Size(barRect.Width, barRect.Height);
				
				if (!mresizeBar.Visible)
					mresizeBar.Show();
			}
			else
			{
				if (mresizeBar.Visible)
					mresizeBar.Hide();
			}
		}

		protected override void OnResize(EventArgs e)
		{
			RepositionControls();

			base.OnResize(e);
		}

		#endregion

		#region Overrides

		protected override void OnWindowsClearing(object sender, EventArgs e)
		{
			base.OnWindowsClearing(sender, e);

			mmaximizedWindow = null;

			Controls.Clear();

			if (!this.AutoDispose)
			{
				Controls.Add(mresizeBar);

				Invalidate();
			}
		}

		protected override void OnWindowInserted(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			base.OnWindowInserted(sender, e);

			Window w = sender as Window;

			if (mwindows.Count == 1)
			{
				Size wSize = w.Size;

				switch(this.Dock)
				{
					case DockStyle.Left:
					case DockStyle.Right:
						wSize.Width += mresizeBar.Width;
						break;
					case DockStyle.Top:
					case DockStyle.Bottom:
						wSize.Height += mresizeBar.Height;
						break;
				}

				this.Size = wSize;

				Controls.Add(w);

				Controls.SetChildIndex(w, 0);
			}
			else
			{
                needle.UI.Controls.Flat.Windows.Forms.ResizeBar bar = new needle.UI.Controls.Flat.Windows.Forms.ResizeBar(mdirection, this);

				Controls.Add(bar);
				Controls.Add(w);

				if (e.Index == 0)
				{
					Controls.SetChildIndex(bar, 0);
					Controls.SetChildIndex(w, 0);
				}
				else
				{
					int	pos = e.Index * 2 - 1;

					Controls.SetChildIndex(bar, pos++);
					Controls.SetChildIndex(w, pos);
				}
			}

			AllocateWindowSpace(w);

			RepositionControls();

			OnRefreshMaximize(EventArgs.Empty);
		}

		protected override void OnWindowRemoving(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			base.OnWindowRemoving(sender, e);

			Window w = sender as Window;

			if (mmaximizedWindow == w)
				mmaximizedWindow = null;

			if (mwindows.Count == 1)
			{
				ControlUtilities.RemoveAt(this.Controls, 0);
			}
			else
			{
				int pos = 0;

				if (e.Index != 0)
					pos = e.Index * 2 - 1;
				ControlUtilities.RemoveAt(this.Controls, pos);
				ControlUtilities.RemoveAt(this.Controls, pos);
			}

			RemoveWindowSpace(w);
		}

		protected override void OnWindowRemoved(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			base.OnWindowRemoved(sender, e);

			RepositionControls();

			OnRefreshMaximize(EventArgs.Empty);
		}

		protected void AllocateWindowSpace(Window w)
		{
			if (mwindows.Count == 1)
			{
				w.ZoneArea = 100m;
			}
			else
			{
				Decimal newSpace = 100m / mwindows.Count;

				Decimal reduceSpace = newSpace / (mwindows.Count - 1);

				Decimal allocatedSpace = 0m;

				foreach(Window entry in mwindows)
				{
					if (entry != w)
					{
						Decimal currentSpace = entry.ZoneArea;

						Decimal xferSpace = reduceSpace;

						if (currentSpace < xferSpace)
							xferSpace = currentSpace;

						currentSpace -= xferSpace;

						currentSpace = Decimal.Round(currentSpace, mspacePrecision);

						entry.ZoneArea = currentSpace;

						allocatedSpace += currentSpace;
					}
				}

				w.ZoneArea = 100m - allocatedSpace;
			}
		}


		public override Restore RecordRestore(Window w, object child, Restore childRestore)
		{
			Content c = child as Content;

			if (c != null)
			{
				StringCollection best;
				StringCollection nex;
				StringCollection previous;

				GetWindowContentFriends(w, out best, out nex, out previous); 

				Restore zoneRestore = new RestoreZoneAffinity(childRestore, c, best, nex, previous); 

				if (mstate == State.Floating)
				{
					return new RestoreContentFloatingAffinity(zoneRestore, mstate, c, best, ZoneHelper.ContentNames(this));
				}
				else
				{
					StringCollection zoneBest;
					StringCollection zoneNext;
					StringCollection zonePrevious;
					StringCollection zoneNextAll;
					StringCollection zonePreviousAll;

					GetZoneContentFriends(c, out zoneBest, out zoneNext, out zonePrevious, 
						out zoneNextAll, out zonePreviousAll); 

					return new RestoreContentDockingAffinity(zoneRestore, mstate, c, zoneBest, 
						zoneNext, zonePrevious,
						zoneNextAll, zonePreviousAll);
				}
			}

			return null;
		}
	
		public override void PropogateNameValue(PropogateName name, object value)
		{
			base.PropogateNameValue(name, value);
            
			SuspendLayout();

			if (name == PropogateName.ZoneMinMax)
			{
				if (mzoneMinMax != (bool)value)
				{
					mzoneMinMax = (bool)value;
                    
					if (!mzoneMinMax)
						mmaximizedWindow = null;  
        
					OnRefreshMaximize(EventArgs.Empty);
				}           
			}
            
			foreach(Control c in this.Controls)
			{
                needle.UI.Controls.Flat.Windows.Forms.ResizeBar rb = c as needle.UI.Controls.Flat.Windows.Forms.ResizeBar;
                
				if (rb != null)
					rb.PropogateNameValue(name, value);
			}
            
			RepositionControls();
            
			ResumeLayout();
		}

		#endregion

		#region Methods

        public bool CanResize(global::needle.UI.Controls.Flat.Windows.Forms.ResizeBar bar)
		{
			if (bar != mresizeBar)
			{
				int barIndex = Controls.IndexOf(bar);

				Window wBefore = Controls[barIndex - 1] as Window;

				Window wAfter = mwindows[mwindows.IndexOf(wBefore) + 1];

				if (((wBefore.ZoneArea <= 0m) && (wAfter.ZoneArea <= 0m)))
					return false;

				if ((mmaximizedWindow != null) && (mmaximizedWindow != wBefore) && (mmaximizedWindow != wAfter))
					return false;
			}

			return true;
		}

        //public VisualStyle Style {
        //    get { return mmanager.Style; }
        //}

        public bool StartResizeOperation(global::needle.UI.Controls.Flat.Windows.Forms.ResizeBar bar, ref Rectangle screenBoundary)
		{
			if (bar == mresizeBar)
			{
				screenBoundary = this.Parent.RectangleToScreen(mmanager.InnerResizeRectangle(this));

				Rectangle zoneBoundary = RectangleToScreen(this.ClientRectangle);

				int minHeight = this.MinimumHeight;
				int minWidth = this.MinimumWidth;

				switch(mstate)
				{
					case State.DockTop:
					{
						int diff = zoneBoundary.Top - screenBoundary.Top + minHeight;
						screenBoundary.Y += diff;
						screenBoundary.Height -= diff;					

						int innerMinimumWidth = mmanager.InnerMinimum.Height;
						screenBoundary.Height -= innerMinimumWidth;
					}
						break;
					case State.DockBottom:
					{
						int diff = zoneBoundary.Bottom - screenBoundary.Bottom - minHeight;
						screenBoundary.Height += diff;					

						int innerMinimumWidth = mmanager.InnerMinimum.Height;
						screenBoundary.Y += innerMinimumWidth;
						screenBoundary.Height -= innerMinimumWidth;
					}
						break;
					case State.DockLeft:
					{
						int diff = zoneBoundary.Left - screenBoundary.Left + minWidth;
						screenBoundary.X += diff;
						screenBoundary.Width -= diff;					

						int innerMinimumWidth = mmanager.InnerMinimum.Width;
						screenBoundary.Width -=	innerMinimumWidth;
					}
						break;
					case State.DockRight:
					{
						int diff = zoneBoundary.Right - screenBoundary.Right - minWidth;
						screenBoundary.Width += diff;

						int innerMinimumWidth = mmanager.InnerMinimum.Width;
						screenBoundary.X += innerMinimumWidth;
						screenBoundary.Width -=	innerMinimumWidth;
					}
						break;
				}
			}
			else
			{
				int barIndex = Controls.IndexOf(bar);

				screenBoundary = RectangleToScreen(this.ClientRectangle);

				Window wBefore = Controls[barIndex - 1] as Window;

				Window wAfter = mwindows[mwindows.IndexOf(wBefore) + 1];
				
				Rectangle rectBefore = wBefore.RectangleToScreen(wBefore.ClientRectangle);
				Rectangle rectAfter = wAfter.RectangleToScreen(wAfter.ClientRectangle);

				if (mdirection == Direction.Vertical)
				{
					screenBoundary.Y = rectBefore.Y + wBefore.MinimalSize.Height;
					screenBoundary.Height -= screenBoundary.Bottom - rectAfter.Bottom;
					screenBoundary.Height -= wAfter.MinimalSize.Height;
				}
				else
				{
					screenBoundary.X = rectBefore.X + wBefore.MinimalSize.Width;
					screenBoundary.Width -= screenBoundary.Right - rectAfter.Right;
					screenBoundary.Width -= wAfter.MinimalSize.Width;
				}
			}

			return true;
		}

        public void EndResizeOperation(global::needle.UI.Controls.Flat.Windows.Forms.ResizeBar bar, int delta)
		{
			if (bar == mresizeBar)
			{
				switch(this.Dock)
				{
					case DockStyle.Left:
						this.Width += delta;
						break;
					case DockStyle.Right:
						this.Width -= delta;
						break;
					case DockStyle.Top:
						this.Height += delta;
						break;
					case DockStyle.Bottom:
						this.Height -= delta;
						break;
				}
			}
			else
			{
				int barIndex = Controls.IndexOf(bar);

				Window w = Controls[barIndex - 1] as Window;

				ModifyWindowSpace(w, delta);
			}
		}

		public void SuppressReposition()
		{
			msuppressReposition = true;
		}

        public bool IsMaximizeAvailable()
        {
            return (mwindows.Count > 1) && mzoneMinMax;
        }

        public bool IsWindowMaximized(Window w)
        {
            return (w == mmaximizedWindow);
        }

        public void MaximizeWindow(Window w)
        {
            mmaximizedWindow = w;

            OnRefreshMaximize(EventArgs.Empty);

            RepositionControls();
        }

        public void RestoreWindow()
        {
            mmaximizedWindow = null;

            OnRefreshMaximize(EventArgs.Empty);

            RepositionControls();
        }

		public void AddHotZones(Redocker redock, HotZoneCollection collection)
		{
			RedockerContent redocker = redock as RedockerContent;

			foreach(Window w in mwindows)
			{
				IHotZoneSource ag = w as IHotZoneSource;

				if (ag != null)
					ag.AddHotZones(redock, collection);
			}

			bool indexAdjustTest = false;
			WindowContent redockWC = redocker.WindowContent;

			if (mwindows.Count == 1)
			{
				if (redockWC != null)
					if (redockWC == mwindows[0])
						if ((redocker.Content == null) || (redockWC.Contents.Count == 1))
							return;
			}
			else
			{
				if (mwindows.Contains(redockWC))
				{
					if ((redocker.Content == null) || (redockWC.Contents.Count == 1))
						indexAdjustTest = true;
				}
			}

			Rectangle zoneArea = this.RectangleToScreen(this.ClientRectangle);

			int length;

			if (mdirection == Direction.Vertical)
				length = zoneArea.Height / (mwindows.Count + 1);
			else
				length = zoneArea.Width / (mwindows.Count + 1);

			AddHotZoneWithIndex(collection, zoneArea, length, 0);

			int addative = 0;		
			int count = mwindows.Count;
			
			for(int index=1; index<count; index++)
			{
				WindowContent wc = mwindows[index] as WindowContent;

				if (indexAdjustTest)
				{	
					if (wc == redockWC)
						--addative;
				}

				AddHotZoneWithIndex(collection,
					wc.RectangleToScreen(wc.ClientRectangle), 
					length, 
					index + addative);
			}

			if (mwindows.Count > 0)
			{
				Rectangle lastArea = zoneArea;
				Rectangle lastSize = zoneArea;

				if (mdirection == Direction.Vertical)
				{
					lastArea.Y = lastArea.Bottom - mhotVectorBeforeControl;
					lastArea.Height = mhotVectorBeforeControl;
					lastSize.Y = lastSize.Bottom - length;
					lastSize.Height = length;
				}
				else
				{
					lastArea.X = lastArea.Right - mhotVectorBeforeControl;
					lastArea.Width = mhotVectorBeforeControl;
					lastSize.X = lastSize.Right - length;
					lastSize.Width = length;
				}

				collection.Add(new HotZoneSequence(lastArea, lastSize, this, mwindows.Count + addative));
			}
		}

		public void ModifyWindowSpace(Window w, Decimal newSpace)
		{
			if (mwindows.Contains(w))
			{
				if (mwindows.Count > 1)
				{
					int otherWindows = mwindows.Count - 1; 

					if (newSpace > 100m)
						newSpace = 100m;
						
					if (newSpace <= 0m)
						newSpace = 0m;		

					if (newSpace != w.ZoneArea)
					{
						Decimal diff = w.ZoneArea - newSpace;					

						if (diff > 0m)
						{
							Decimal extra = diff / otherWindows;

							Decimal allocated = 0m;
							int found = 0;

							foreach(Window target in mwindows)
							{
								if (target != w)
								{
									target.ZoneArea += extra;

									allocated += extra;

									found++;

									if (found == otherWindows)
										target.ZoneArea += (diff - allocated);
								}
							}
						}
						else
						{
							diff = -diff;

							while(diff > 0m)
							{
								Decimal extra = diff / otherWindows;

								foreach(Window target in mwindows)
								{
									if (target != w)
									{
										if (target.ZoneArea > 0m)
										{
											if (target.ZoneArea < extra)
											{
												diff -= target.ZoneArea;
		
												target.ZoneArea = 0m;
											}
											else
											{
												target.ZoneArea -= extra;

												diff -= extra;
											}
										}
									}
								}
							}
						}

						w.ZoneArea = newSpace;
					}
				}
			}

			RepositionControls();
		}
		
		#endregion

		#region Properties
		
		public Color ResizeBarColor
		{
			get { return mmanager.ResizeBarColor; }
		}
            
		public int ResizeBarVector
		{
			get { return mmanager.ResizeBarVector; }
		}
            
		public Color BackgroundColor
		{
			get { return mmanager.BackColor; }
		}
		
		public override int MinimumWidth 
		{ 
			get { return mresizeBar.Width * 5; }
		}
		
		public override int MinimumHeight
		{ 
			get { return mresizeBar.Height * 6; } 
		}

		public override DockStyle Dock
		{
			get { return base.Dock; }

			set
			{
				base.Dock = value;

				RepositionControls();
			}
		}

		public Direction Direction
		{
			get { return mdirection; }

			set
			{
				if (mdirection != value)
					mdirection = value;
			}
		}

		public override State State
		{
			get {return base.State;}
			set 
			{
				base.State = value;

				foreach(Window w in mwindows)
					w.State = value;

				RepositionControls();
			}
		}

		#endregion

    }
}
